#pragma once

#include "glare.core.Prerequisites.h"
#include "glare.core.Viewport.h"
#include "glare.math.Matrix4.h"
#include "glare.core.GpuPrimitiveType.h"
#include "glare.core.Box.h"

namespace Glare {

	class DrawContext
	{
	public : DrawContext() {}
	public : virtual ~DrawContext() {}

	public : virtual void ClearRenderTarget(RenderTarget* render_target, const ColourValue& clear_color) = 0;
	public : virtual void Draw(const uint& vertex_count, const uint& start_vertex = 0) = 0;
	public : virtual void DrawIndexed(const uint& index_count, const uint& start_index, const uint& vertex_offset) = 0;
	public : virtual void UpdateGpuResource(GpuResource* destination_resource, const uint& dest_sub_resource, Box* dest_box, const void* src_data, const uint& src_row_pitch, const uint& src_depth_pitch) = 0;

	/// InputAssembler Stage API
	public : virtual void IA_SetIndexBuffer(GpuBuffer* buffer, const bool& format_32bit, const uint& offset) = 0;
	public : virtual void IA_SetVertexBuffer(const GpuVertexBufferBinding& vertex_buffer_binding, const uint& start_slot = 0) = 0;
	public : virtual void IA_SetVertexBuffers(const GpuVertexBufferBinding bindings[], const uint& num_bindings, const uint& start_slot = 0) = 0;
	public : virtual void IA_SetPrimitiveType(const GpuPrimitive::Type& primitive_type) = 0;
	public : virtual void IA_SetInputDeclaration(ShaderInputDeclaration* declaration) = 0;

	/// VertexTransform Stage API
	/** Sets the world transform matrix. */
	public : virtual void VT_SetWorldMatrix(const Matrix4 &m) = 0;

	/** Sets multiple world matrices (vertex blending). */
	public : virtual void VT_SetWorldMatrices(const Matrix4* m, unsigned short count) { VT_SetWorldMatrix(Matrix4::IDENTITY); }

	/** Sets the view transform matrix */
	public : virtual void VT_SetViewMatrix(const Matrix4 &m) = 0;

	/** Sets the projection transform matrix */
	public : virtual void VT_SetProjectionMatrix(const Matrix4 &m) = 0;

	/// VertexShader Stage API
	public : virtual void VS_SetVertexShader(VertexShader* program) = 0;
	public : virtual void VS_SetConstantBuffer(const uint& slot, GpuBuffer* constant_buffer) = 0;

	/// Rasterizer Stage API
	public : virtual void RS_SetViewport(const Viewport& viewport) = 0;
	public : virtual void RS_SetViewports(uint num_viewports, const Viewport* viewport_array) = 0;

	/// PixelShader Stage API
	public : virtual void PS_SetPixelShader(PixelShader* program) = 0;
	public : virtual void PS_SetSamplerState(const uint& slot, SamplerState* sampler_state) = 0;
	public : virtual void PS_SetShaderResource(const uint& slot, ShaderResourceView* resource_view) = 0;

	/// OutputMerger Stage API
	public : virtual void OM_SetRenderTarget(RenderTarget* render_target, DepthBuffer* depth_buffer) = 0;
	public : virtual void OM_SetMultiRenderTargets(RenderTarget** render_targets, int num_targets, DepthBuffer* depth_buffer) = 0;

	public : virtual Driver* GetDriver() const = 0;
	};

}